import * as ol from '../ol'
import 'ol/ol.css';

class Measure {
    /**
     * @constructor Measure
     * @description 测量。适用于距离测量和面积测量
     * @param {Object} map - 地图对象
     * @param {Boolean} [isAreaMeasurement=false] - 是否为面积测量
     * @example
     * // 距离测量
     * const measure  = new GISMap.Measure(map);
     * // 绘制结束事件
     * measure.interaction.on("drawend", function(event) {
     *   console.log(measure.getResult()); // 输出测量结果
     * });
     */
    constructor(map, isAreaMeasurement = false) {
        // 将传入的地图对象赋值给类的 map 属性
        this.map = map;
        // 创建一个空的矢量数据源对象 source
        this.source = new ol.source.Vector();
        // 创建一个矢量图层对象 layer，并将 source 设置为该图层的数据源
        this.layer = new ol.layer.Vector({
            source: this.source
        });
        // 创建一个绘制交互对象 interaction，指定绘制类型为 "LineString"（线）或 "Polygon"（多边形）并设置数据源为 source
        this.interaction = new ol.interaction.Draw({
            type: isAreaMeasurement ? "Polygon" : "LineString",
            source: this.source,
        });
        // 初始化测量结果
        this.output = null;
        // 初始化测量结果提示框和相关变量
        this.measureTooltip = null;
        this.measureTooltipElement = null;
        // 创建一个用于显示鼠标移动时的测量结果提示框的 Overlay 对象
        this.tooltipOverlay = new ol.Overlay({
            element: document.createElement("div"),
            offset: [0, -15],
            positioning: "bottom-center",
        });
        // 将图层添加到地图中
        this.map.addLayer(this.layer);
        // 将交互对象添加到地图中
        this.map.addInteraction(this.interaction);
        // 绑定 onDrawStart 和 onDrawEnd 方法到对应事件处理函数
        this.interaction.on("drawstart", this.onDrawStart.bind(this));
        this.interaction.on("drawend", this.onDrawEnd.bind(this));
    }
    // 绘制结束的测量结果提示框
    createMeasureTooltip() {
        this.measureTooltipElement = document.createElement("div");
        // 创建一个新的 HTML 元素作为绘制结束时的测量结果提示框的容器，并为其设置样式类名
        this.measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
        this.measureTooltip = new ol.Overlay({
            // 创建一个绘制结束时的测量结果提示框的 Overlay 对象，并指定其相关属性，如容器元素、位置偏移和定位方式
            element: this.measureTooltipElement,
            offset: [0, -15],
            positioning: "bottom-center",
        });
        // 将绘制结束时的测量结果提示框添加到地图的 Overlays 中
        this.map.addOverlay(this.measureTooltip);
    }
    formatLength(line) {
        const length = ol.sphere.getLength(line);
        // 绘制的线长度
        let output;
        let unit;
        if (length > 1000) {
            unit = 'km'
            // 根据线的长度进行单位转换并得到格式化后的输出结果
            output = `${(length / 1000).toFixed(2)}`;
        } else {
            unit = 'm'
            // 根据线的长度进行单位转换并得到格式化后的输出结果
            output = `${length.toFixed(2)}`;
        }
        return {
            output: output,
            unit: unit
        };
    }
    formatArea(polygon) {
        const area = ol.sphere.getArea(polygon);
        // 绘制的多边形面积
        let output;
        let unit;
        if (area > 1000000) {
            unit = 'km²'
            // 根据多边形的面积进行单位转换并得到格式化后的输出结果
            output = `${(area / 1000000).toFixed(2)}`;
        } else {
            unit = 'm²'
            // 根据多边形的面积进行单位转换并得到格式化后的输出结果
            output = `${area.toFixed(2)}`;
        }
        return {
            output: output,
            unit: unit
        };
    }
    onPointerMove(event) {
        // 获取鼠标移动时的坐标
        const tooltipCord = event.coordinate;
        this.map.addOverlay(this.tooltipOverlay);
        // 更新测量结果提示框的位置
        this.tooltipOverlay.setPosition(tooltipCord);
    }
    onDrawStart(event) {
        // 清空数据源中的所有要素
        // this.source.clear();
        // 创建新的测量结果提示框
        this.createMeasureTooltip();
        // 监听鼠标移动事件，并将触发的事件绑定到 onPointerMove 方法
        this.map.on("pointermove", this.onPointerMove.bind(this));
    }
    onDrawEnd(event) {
        // 移除监听鼠标移动事件绑定的方法
        this.map.un("pointermove", this.onPointerMove.bind(this));
        // 获取绘制要素的几何信息
        const geometry = event.feature.getGeometry();
        let output;
        if (geometry instanceof ol.geom.Polygon) {
            // 计算绘制的多边形的面积
            output = this.formatArea(geometry);
        } else if (geometry instanceof ol.geom.LineString) {
            // 计算绘制的线的长度
            output = this.formatLength(geometry);
        }
        // 将测量结果显示在绘制结束时的测量结果提示框中
        this.measureTooltipElement.innerHTML = `${output.output}${output.unit}`;
        // 将绘制结束时的测量结果提示框的位置设置为几何信息的中点
        this.measureTooltip.setPosition(ol.extent.getCenter(geometry.getExtent()));
        // 更新绘制结束时的测量结果提示框的样式类名，使其成为静态状态
        this.measureTooltipElement.className =
            "ol-tooltip ol-tooltip-static ol-tooltip-measure";
        // 调整绘制结束时的测量结果提示框的偏移
        this.measureTooltip.setOffset([0, -7]);
        // 重置相关变量
        this.measureTooltip = null;
        this.measureTooltipElement = null;
        // 创建新的测量结果提示框
        this.createMeasureTooltip();
        console.log(output);
        // 测量结果
        this.output = output;
    }
    /**
     * 获取测量结果
     * @method
     * @name Measure#getResult
     * @description 获取测量结果
     * @returns {Object | null}
     */
    getResult() {
        return this.output;
    }
}

export default Measure